package com.llongwill.slg.gateway.user.service;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.llongwill.slg.gateway.user.support.SjyVistorUserLoginRequest;
import com.llongwill.slg.gateway.user.support.UserLoginRequest;
import com.llongwill.slg.gateway.user.support.UserLoginResult;
import com.llongwill.slg.teaching.visitor.appservice.ITeachingResearchVisitorAppService;
import com.llongwill.slg.teaching.visitor.entity.TeachingExecuteVisitorDTO;
import com.llongwill.slg.user.appservice.IUserQueryAppService;
import com.llongwill.slg.user.entity.UserDTO;
import com.llongwill.slg.user.entity.UserTokenResultDTO;
import com.xiangff.base.business.BaseBusinessService;
import com.xiangff.base.framework.encrypt.MD5Encoder;
import com.xiangff.base.framework.encrypt.XOREncoderAndDecoder;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;

import static com.llongwill.slg.gateway.common.GatewayConstants.KEYS_SCHOOL_ID;
import static com.xiangff.base.framework.constants.SecurityConstants.USER_HEADER;
import static com.xiangff.base.framework.resp.DefaultResponseCodeEnum.LOGIN_FAIL;


/**
 * 用户登录服务
 *
 * @author xiangff
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class UserLoginService extends BaseBusinessService {


    private final IUserQueryAppService userQueryAppService;
    private final ITeachingResearchVisitorAppService teachingResearchVisitorAppService;

    @Autowired
    private XOREncoderAndDecoder xOREncoderAndDecoder;
    @Autowired
    private MD5Encoder mD5Encoder;

    /**
     * userToken登录
     *
     * @param userToken
     * @return
     */
    public UserLoginResult userTokenLogin(String userToken, String xBusinessHeader) {
        UserTokenResultDTO userTokenResult = userQueryAppService.getUserByUserToken(userToken, xBusinessHeader);
        if (Objects.isNull(userTokenResult)) {
            return UserLoginResult.builder()
                    .loginSuccess(false)
                    .loginCode(LOGIN_FAIL.getCode())
                    .loginMessage(LOGIN_FAIL.getMessage())
                    .build();
        }
        if (!Boolean.TRUE.equals(userTokenResult.getSuccess()) || Objects.isNull(userTokenResult.getResult())) {
            return UserLoginResult.builder()
                    .loginSuccess(false)
                    .loginCode(userTokenResult.getResultCode())
                    .loginMessage(userTokenResult.getResultMessage())
                    .build();
        }
        //登录用户
        UserDTO userDTO = userTokenResult.getResult();
        StpUtil.login(userDTO.getId());
        StpUtil.getTokenSession().set("SCHOOL_ID", userDTO.getSchoolId());
        //登录成功
        return UserLoginResult.builder()
                .loginSuccess(true)
                .userId(userDTO.getId())
                .userName(userDTO.getUserName())
                .loginName(userDTO.getLoginName())
                .token(StpUtil.getTokenInfo().getTokenValue())
                .schoolId(userDTO.getSchoolId())
                .userRoles(userDTO.getRoles())
                .build();
    }

    /**
     * 登录
     *
     * @param loginName 用户名
     * @param password  密码
     * @return UserLoginResult
     */
    public UserLoginResult login(String loginName, String password) {
        //查询登录用户
        UserDTO userByLoginName = userQueryAppService.getUserByLoginName(loginName);
        if (userByLoginName == null) {
            return UserLoginResult.builder()
                    .loginSuccess(false)
                    .loginCode(LOGIN_FAIL.getCode())
                    .loginMessage(LOGIN_FAIL.getMessage())
                    .build();
        }
        //MD5(password)
        String inputPassword = mD5Encoder.encode(xOREncoderAndDecoder.encode(password));
        if (!inputPassword.equalsIgnoreCase(userByLoginName.getPassword())) {
            return UserLoginResult.builder()
                    .loginSuccess(false)
                    .loginCode(LOGIN_FAIL.getCode())
                    .loginMessage(LOGIN_FAIL.getMessage())
                    .build();
        }
        //登录
        StpUtil.login(userByLoginName.getId());
        if (StringUtils.isNotBlank(userByLoginName.getSchoolId())) {
            StpUtil.getSession().set(KEYS_SCHOOL_ID, userByLoginName.getSchoolId());
        }
        StpUtil.getSession().set(USER_HEADER, userByLoginName.getUserName());
        //登录成功
        return UserLoginResult.builder()
                .loginSuccess(true)
                .userId(userByLoginName.getId())
                .schoolId(userByLoginName.getSchoolId())
                .userName(userByLoginName.getUserName())
                .loginName(userByLoginName.getLoginName())
                .token(StpUtil.getTokenInfo().getTokenValue())
                .userRoles(userByLoginName.getRoles())
                .build();
    }

    /**
     * 获取用户登录Token信息
     *
     * @return
     */
    public UserDTO loginUser() {
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        return UserDTO
                .builder()
                .userName(tokenInfo.getTokenName())
                .id(tokenInfo.getTokenValue())
                .build();
    }

    /**
     * 登录id登录
     *
     * @param loginId
     * @return
     */
    public UserLoginResult loginByLoginId(String loginId) {
        //查询登录用户
        UserDTO userByLoginName = userQueryAppService.getUserByLoginId(loginId);
        if (userByLoginName == null) {
            return UserLoginResult.builder()
                    .loginSuccess(false)
                    .loginCode(LOGIN_FAIL.getCode())
                    .loginMessage(LOGIN_FAIL.getMessage())
                    .build();
        }
        //登录
        StpUtil.login(userByLoginName.getId());
        if (StringUtils.isNotBlank(userByLoginName.getSchoolId())) {
            StpUtil.getSession().set(KEYS_SCHOOL_ID, userByLoginName.getSchoolId());
        }
        //登录成功
        return UserLoginResult.builder()
                .loginSuccess(true)
                .userId(userByLoginName.getId())
                .schoolId(userByLoginName.getSchoolId())
                .userName(userByLoginName.getUserName())
                .loginName(userByLoginName.getLoginName())
                .token(StpUtil.getTokenInfo().getTokenValue())
                .userRoles(userByLoginName.getRoles())
                .build();
    }

    /**
     * 游客登录
     *
     * @param loginRequest
     * @return
     */
    public UserLoginResult visitorLogin(UserLoginRequest loginRequest) {
        String username = loginRequest.getUsername();


        UserDTO visitorUser = UserDTO.builder().id(getStringId()).loginName(username).build();
        //登录
        StpUtil.login(visitorUser.getId());
        if (StringUtils.isNotBlank(visitorUser.getSchoolId())) {
            StpUtil.getSession().set(KEYS_SCHOOL_ID, visitorUser.getSchoolId());
        }
        //登录成功
        return UserLoginResult.builder()
                .loginSuccess(true)
                .userId(visitorUser.getId())
                .schoolId(visitorUser.getSchoolId())
                .userName(visitorUser.getUserName())
                .loginName(visitorUser.getLoginName())
                .token(StpUtil.getTokenInfo().getTokenValue())
                .userRoles(visitorUser.getRoles())
                .build();
    }

    /**
     * 实现访问者登录功能
     * 通过调用教学研究访问者应用服务，根据教学执行ID和用户名获取访问者信息，并进行登录验证
     *
     * @param loginRequest 访问者登录请求对象，包含教学执行ID和用户名
     * @return 返回用户登录结果对象，包括登录成功与否、用户ID、学校ID、用户名、登录名、令牌和用户角色
     */
    public UserLoginResult sjyVisitorLogin(SjyVistorUserLoginRequest loginRequest) {
        // 根据提供的教学执行ID和用户名查询访问者信息
        TeachingExecuteVisitorDTO visitorByName =
                teachingResearchVisitorAppService.getVisitorByName(loginRequest.getTeachingExecuteId(), loginRequest.getUsername());

        if (visitorByName != null) {
            // 构建用户信息对象，用于登录
            UserDTO visitorUser = UserDTO.builder()
                    .id(visitorByName.getVisitorUserId())
                    .loginName(visitorByName.getVisitorName())
                    .userName(visitorByName.getVisitorName())
                    .schoolId(visitorByName.getSchoolId())
                    .build();

            // 执行登录操作
            StpUtil.login(visitorUser.getId());
            // 设置学校ID到会话中
            if(StringUtils.isNotBlank(visitorByName.getSchoolId())){
                StpUtil.getSession().set(KEYS_SCHOOL_ID, visitorByName.getSchoolId());
            }

            // 登录成功，返回登录结果
            return UserLoginResult.builder()
                    .loginSuccess(true)
                    .userId(visitorUser.getId())
                    .schoolId(visitorUser.getSchoolId())
                    .userName(visitorUser.getUserName())
                    .loginName(visitorUser.getLoginName())
                    .token(StpUtil.getTokenInfo().getTokenValue())
                    .userRoles(visitorUser.getRoles())
                    .build();
        }

        // 登录失败，返回登录结果
        return UserLoginResult.builder()
                .loginSuccess(false)
                .build();
    }


    /**
     * 用户登出函数
     * 本函数负责处理用户的登出操作。特定业务逻辑根据传入的头部信息xBusinessHeader进行处理。
     * 目前仅当xBusinessHeader为"SKT"时，会有特定的处理逻辑需要实现。其他情况下，直接调用登出操作。
     *
     * @param idToken 用户的身份令牌，用于验证用户身份。
     * @param xBusinessHeader 业务头部信息，用于区分不同的业务场景或合作伙伴。
     */
    public void logout(String idToken, String xBusinessHeader) {
        // 当业务头部为"SKT"时，此处应实现特定的登出逻辑
        if("SKT".equals(xBusinessHeader)){
            //TODO: 实现SKT业务的登出处理逻辑
        }
        // 执行通用的登出操作
        StpUtil.logout();
    }
}
